package agent;
import java.util.ArrayList;
import java.util.Hashtable;

import dao.DaoAgente;

import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.SequentialBehaviour;
import jade.lang.acl.ACLMessage;
import model.Coordenada;
import model.Rota;
import model.Shape;
import model.Stop;
import model.SubRota;



public class AgBuscador extends Agent{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Coordenada origem;
	private Coordenada destino;
	private Stop stopOrigem;
	
	protected void setup(){
		
		SequentialBehaviour seq = new SequentialBehaviour(this){//composto

			private static final long serialVersionUID = 1L;

			public int onEnd(){
				myAgent.doDelete();
				return 0;
			}
			
		};
		
		seq.addSubBehaviour(new Behaviour(this){ //recebe mensagen com os dados da busca
			
			private static final long serialVersionUID = 1L;
			 Hashtable obj; 
			public void action(){
				System.out.println("Exec comportamento...RECEBE MSG"+myAgent.getName());
				ACLMessage msg = receive();
				if(msg !=null){
					try{
						obj = new Hashtable();
						obj =  (Hashtable) msg.getContentObject();
						origem = (Coordenada) obj.get("origem");
						destino = (Coordenada) obj.get("destino");
						stopOrigem = (Stop) obj.get("stopOrigem");
						
						//teste
						System.out.println("COMPORTAMENTO BUSCA ROTA "+getName());
						System.out.println("Lat origem" +origem.getLat());
						System.out.println("Lat destino" +destino.getLat());
						System.out.println("Lat stopOrigem nome" +stopOrigem.getStop_name());
					}catch(Exception e){
						e.printStackTrace();
					}
				}
				
			}
			
			public boolean done(){
				if(this.obj == null){
					block();
					return false;
				}
				else
					return true;
				
			}
		});//fim do recebe mensagem
				
		
		seq.addSubBehaviour(new Behaviour(this){
			
			ArrayList<Rota> rotas = new ArrayList<Rota>();
			ArrayList<Rota> rotasOk = new ArrayList<Rota>();
			ArrayList<SubRota> subRotas = new ArrayList<SubRota>();
			Stop stopDestino = new Stop();
//			private Coordenada origem;
//			private Coordenada destino;
//			private Stop stopOrigem;
//			private int raioOrigem;
//			private int raioDestino;
			
//			public CpBuscaRota(Agent agente, Coordenada origem, Coordenada destino, Stop stopOrigem){
//				super(agente);
//				rotas = new ArrayList<Rota>();
//				rotasOk = new ArrayList<Rota>();
//				subRotas = new ArrayList<SubRota>();
//				stopOrigem = new Stop();
//				this.origem = origem;
//				this.destino = destino;
//			}
			
			
			
			@Override
			public void action() {
				System.out.println("Exec comportamento...bUSCA ROTA"+myAgent.getName());
				/*rotasOk = */buscar(origem, destino, stopOrigem, stopDestino, subRotas);
	//			AreaRotas.setRotas(rotasOk);
				//block();
				takeDown();
			}

			@Override
			public boolean done() {
				if(AreaRotas.getNumRotas() > 2){
					return true;
				}
				
				return false;
			}
			
			public /*ArrayList<Rota>*/ void buscar(Coordenada origem, Coordenada destino, Stop stopOrigem, Stop stopDestino, ArrayList<SubRota> subRotas){
				
				//int raioOrigem = 0;
				int raioDestino = 0;
				int raioShape = 0;
				//ArrayList<Stop> stopsOrigem = new ArrayList<Stop>();
				ArrayList<Stop> stopsDestino = new ArrayList<Stop>();
				ArrayList<Shape> forma = new ArrayList<Shape>();
				ArrayList<String> trips = new ArrayList<String>();
//				Stop stopDestino = new Stop();
				Shape shapeOrigem = new Shape();
				Shape shapeDestino = new Shape();
				SubRota srt = new SubRota();
				Rota rota = new Rota();
				boolean raioDestinoTocou = false;
				DaoAgente dao = new DaoAgente();
				double distDestOrig = destino.calculaDistancia(origem.getLat(), origem.getLon());
				
					
				//pegando pontos no raio de origem (aumentando o raio de origem até encontrar)
//				while(stopsOrigem.size() == 0){
//					raioOrigem++;
//					stopsOrigem = dao.getStopsOfCoordRaio(origem.getLat(), origem.getLon(), raioOrigem);
//					
//					/*VERIFICAR SE A DISTANCIA À PÉ DO STOP ENCONTRADO PARA ORIGEM É SUPERIOR A DISTÂNCIA À PE ENTRE ORIGEM E DESTINO!!!!*/
//					
//				}
				
				//pegando viagens, testando o primeiro ponto com raio de destino (aumentando o raio de destino até encontrar)
				
				//for(int i = 0; i < stopsOrigem.size(); i++){
				
				
				//Aumentando raio de destino para encontrar as viagens
				while(trips.size() == 0){
					
					raioDestino++;
					trips = dao.getTripsOfStopCoordRaio(stopOrigem.getStop_id(), destino.getLat(), destino.getLon(), raioDestino);
				}
					
				for(int t = 0; t < trips.size(); t++){
					if(raioDestinoTocou)
						break;
					stopOrigem = dao.getStopOfTripStopId(trips.get(t), stopOrigem.getStop_id());
							
					//pegando stops no destino, da viagem de indice t
					stopsDestino = dao.getStopsOfCoordRaio(trips.get(t), destino.getLat(), destino.getLon(), raioDestino);
					
					
					//testando se raio tocou
					for(int i = 0; i < stopsDestino.size(); i++){
						if(stopOrigem.getStop_id() == stopsDestino.get(i).getStop_id()){
							raioDestinoTocou = true;
							break;
						}
					}
					
					if(raioDestinoTocou)
						break;
					
								
					//eliminando os stops do destino de direção contraria
					ArrayList<Stop> stopsDestinoTemp = new ArrayList<Stop>();
					for(int i = 0; i < stopsDestino.size(); i++){
						if(stopOrigem.getStop_sequence() < stopsDestino.get(i).getStop_sequence()){
							stopsDestinoTemp.add(stopsDestino.get(i));
						}
					}
					if(stopsDestinoTemp.size() == 0){
						continue;
					}
					else{
						stopsDestino = stopsDestinoTemp;
						//identificando o stop mais próximo do destino
						stopDestino = stopsDestino.get(0);
						double distStopDestino;
						double distStopDestinoTeste;
						for(int i = 0; i < stopsDestino.size(); i++){
							distStopDestino = destino.calculaDistancia(stopDestino.getStop_lat(), stopDestino.getStop_lon());
							distStopDestinoTeste = destino.calculaDistancia(stopsDestino.get(i).getStop_lat(), stopsDestino.get(i).getStop_lon());
							if(distStopDestinoTeste < distStopDestino){
								stopDestino = stopsDestino.get(i);
							}
						}
						double distDestStDest = destino.calculaDistancia(stopDestino.getStop_lat(), stopDestino.getStop_lon());
						if(distDestStDest > distDestOrig){
							continue;
						}
									
						//Aqui já tenho "stopOrigem" e "stopDestino" com linha viagem.
						
						
						///buscando Shapes de origem
						ArrayList<Shape> shapesOrigem = new ArrayList<Shape>();
						for(raioShape = 1; shapesOrigem.size() == 0; raioShape++){
							shapesOrigem = dao.getShapesOfTripCoordRaio(trips.get(t), stopOrigem.getStop_lat(), stopOrigem.getStop_lon(), raioShape);
						}
						
						//encontrando shape mais pròximo do stop de Origem
						Coordenada coordStopOrig = new Coordenada(stopOrigem.getStop_lat(), stopOrigem.getStop_lon());
						shapeOrigem = shapesOrigem.get(0);
						double distShapeOrigem;
						double distShapeOrigemTeste;
						for(int i = 0; i < shapesOrigem.size(); i++){
							distShapeOrigem = coordStopOrig.calculaDistancia(shapeOrigem.getShape_pt_lat(), shapeOrigem.getShape_pt_lon());
							distShapeOrigemTeste = coordStopOrig.calculaDistancia(shapesOrigem.get(i).getShape_pt_lat(), shapesOrigem.get(i).getShape_pt_lon());
							if(distShapeOrigemTeste < distShapeOrigem){
								shapeOrigem = shapesOrigem.get(i);
							}
						}
						
						
						
						///buscando Shapes de Destino
						ArrayList<Shape> shapesDestino = new ArrayList<Shape>();
						for(raioShape = 1; shapesDestino.size() == 0; raioShape++){
							shapesDestino = dao.getShapesOfTripCoordRaio(trips.get(t), stopDestino.getStop_lat(), stopDestino.getStop_lon(), raioShape);
						}
						
						//encontrando shape mais pròximo do stop de Destino
						Coordenada coordStopDest = new Coordenada(stopDestino.getStop_lat(), stopDestino.getStop_lon());
						shapeDestino = shapesDestino.get(0);
						double distShapeDestino;
						double distShapeDestinoTeste;
						for(int i = 0; i < shapesDestino.size(); i++){
							distShapeDestino = coordStopDest.calculaDistancia(shapeDestino.getShape_pt_lat(), shapeDestino.getShape_pt_lon());
							distShapeDestinoTeste = coordStopDest.calculaDistancia(shapesDestino.get(i).getShape_pt_lat(), shapesDestino.get(i).getShape_pt_lon());
							if(distShapeDestinoTeste < distShapeDestino){
								shapeDestino = shapesDestino.get(i);
							}
						}
						
						///Aqui já tenho "shapeOrigem" e "shapeDestino" com linha viagem.
						
						
						//buscando forma da subrota para ser desenhada
						if(shapeOrigem.getShape_id() == shapeDestino.getShape_id()){
							forma = dao.getShapesOfTripOrigemDestino(shapeOrigem.getShape_id(), shapeOrigem.getShape_pt_sequence(), shapeDestino.getShape_pt_sequence());
						}
						else{
							System.out.println("SHAPE DE ORIGEM ID DIFERENTE DO SHAPE DE DESTINO ID!!!!!");
						}
						
						//Montando SubRota
						srt.setForma(forma);
						srt.setStopOrigem(stopOrigem);
						srt.setStopDestino(stopDestino);
						srt = dao.preencheSubrota(trips.get(t), srt);
						subRotas.add(srt);
						
						if(raioDestino <= 2){
							rota.setSubrotas(subRotas);
							AreaRotas.addRota(rota);
//							block();
//							this.rotas.add(rota);
//							return rotas;
						}
						else{
						//recurção
							Coordenada novaOrigem = new Coordenada(stopDestino.getStop_lat(), stopDestino.getStop_lon());
							Stop novoStopOrigem = stopDestino;
							Stop novoStopDestino = new Stop();
							System.out.println("Recurção");
							buscar(novaOrigem, destino, novoStopOrigem, novoStopDestino, subRotas);
						}
						
					}
					
				}
				if(subRotas.size() > 0){
					
					rota.setSubrotas(subRotas);
					AreaRotas.addRota(rota);
					block();
				}else{
					block();
				}
				
//				this.rotas.add(rota);
//				return rotas;
					
			}
			
			
			
			
			public boolean toucouRaio(ArrayList<String> trips, double lat, double lon, int raioDestino, Stop stopOrigem){
				boolean tocaRaio = false;
				DaoAgente dao = new DaoAgente();
				//pegando stops no destino, da viagem de indice t
				for(int t = 0; t < trips.size(); t++){
					ArrayList<Stop> stopsDestino = dao.getStopsOfCoordRaio(trips.get(t), destino.getLat(), destino.getLon(), raioDestino);
					
					//Verificando se o raio destino tocou o stopOrigem
					for(int i = 0; i < stopsDestino.size(); i++){
						
						if((stopOrigem.getStop_lat() == stopsDestino.get(i).getStop_lat()) && (stopOrigem.getStop_lon() == stopsDestino.get(i).getStop_lon())){
							tocaRaio = true;
						}
						
					}
					if(tocaRaio){
						return tocaRaio;
					}
				}
				return tocaRaio;
				
			}
			
			//gets e sets
				public ArrayList<Rota> getRotas() {
					return rotas;
				}

				public void setRotas(ArrayList<Rota> rotas) {
					this.rotas = rotas;
				}
				
			
		}); 
				
				
				
				
				
				
//CpBuscaRota(this, origem, destino, stopOrigem));
			
		addBehaviour(seq);

		
		
	}
	
	protected void takeDown(){
		System.out.println("Numero de rotas = "+AreaRotas.getNumRotas());
		ArrayList<Rota> rotas = AreaRotas.getRotas();
		System.out.println("Rotas: "+rotas.size());
		for(int i=0; i<rotas.size(); i++){
			System.out.println("Rota numero: "+(i+1)+"\t\t\tNumero de Subrotas: "+rotas.get(i).getSubrotas().size());
			for(int j=0; j<rotas.get(i).getSubrotas().size(); j++){
				System.out.println("Rota numero: "+(i+1)+"\t\t\tSubrota numero: "+(j+1));
				System.out.println("Stop de origem ID: "+rotas.get(i).getSubrotas().get(j).getStopOrigem().getStop_id());
				System.out.println("Stop de destino ID: "+rotas.get(i).getSubrotas().get(j).getStopDestino().getStop_id());
				System.out.println("Origem LAT: "+rotas.get(i).getSubrotas().get(j).getOrigem().getLat()+"\t\t\tOrigem LON: "+rotas.get(i).getSubrotas().get(j).getOrigem().getLon());
				System.out.println("Destino LAT: "+rotas.get(i).getSubrotas().get(j).getDestino().getLat()+"\t\tDestino LON: "+rotas.get(i).getSubrotas().get(j).getDestino().getLon());
				System.out.println("Distancia: "+rotas.get(i).getSubrotas().get(j).getDistancia());
				System.out.println("Viagem: "+rotas.get(i).getSubrotas().get(j).getViagem());
				System.out.println("Linha: "+rotas.get(i).getSubrotas().get(j).getLinha());
				System.out.println("Descrição: "+rotas.get(i).getSubrotas().get(j).getDescricaoLong());
				System.out.println("Tipo: "+rotas.get(i).getSubrotas().get(j).getTipo());
				System.out.printf("Tarifa: R$ %.2f\n",rotas.get(i).getSubrotas().get(j).getTarifa());
				System.out.println("Cor: "+rotas.get(i).getSubrotas().get(j).getCor());
			}
		}
		System.out.println("Agente: "+getAID().getName()+" esta fianlizado...");
		
	}
	
	
	

}
